package com.njym.java.security.app.service.impl; /**
 * @Title: WXserviceImpl
 * @ProjectName family-security
 * @Description: TODO
 * @author 71705
 * @date 2020/2/2513:34
 */

import com.alipay.api.domain.AlipayTradeRefundApplyModel;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayConfig;
import com.github.wxpay.sdk.WXPayUtil;
import com.njym.java.security.app.biz.*;
import com.njym.java.security.app.entity.*;
import com.njym.java.security.app.service.WXservice;

import com.njym.java.security.app.util.WXConfigUtil;
import com.njym.java.security.app.util.WxMD5Util;
import com.njym.java.security.common.tradeStatusConfig.AliTradeStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.util.*;

/**
 * @program: family-security
 *
 * @description:
 *
 * @author: lijie
 *
 * @create: 2020-02-25 13:34
 **/
@Service
public class WXserviceImpl implements WXservice {
    private static final Logger logger = LoggerFactory.getLogger("MainLogger");
    public static final String SPBILL_CREATE_IP = "127.0.0.1";
//    public static final String NOTIFY_URL = "http://jtjs.aimanrenjian.net/weixin/notify.json";
    public static final String NOTIFY_URL = "http://jtjs.aimanrenjian.net/api/app/weixin/notify.json";

    public static final String TRADE_TYPE_APP = "APP";

    @Resource
    private CourseCatalogueBiz courseCatalogueBiz;

    @Autowired
    private PlatformTransactionManager txManager;

    @Resource
    private PaymentRecordBiz paymentRecordBiz;


    @Autowired
    private FamilyUserBiz familyUserBiz;

    @Autowired
    private UserBiz userBiz;

    @Autowired
    private IdentityApplyBiz identityApplyBiz;

    @Autowired
    private FamilyWalletRecordBiz familyWalletRecordBiz;

    /**
     * 调用官方SDK 获取预支付订单等参数
     * @return
     * @throws Exception
     */
    @Override
    public Map<String, String> dounifiedOrder(Integer userId, Integer lessonId, String userName, Integer classId, String code) throws Exception {

        String attach = "{\"user_id\":\"" + userId + "\"}";
        //生成商户订单号，不可重复
        String out_trade_no = "wxpay" + System.currentTimeMillis();


        CourseCatalogue courseCatalogue = courseCatalogueBiz.selectById(lessonId);
        //价格
        int  total_fees = (int) (courseCatalogue.getPrice()*100);
        String   total_fee = String.valueOf(total_fees);

        PaymentRecord paymentRecord = new PaymentRecord();
        paymentRecord.setChargeUserId(userId);
        paymentRecord.setChargeUserName(userName);
        paymentRecord.setLessonId(lessonId);
        paymentRecord.setOutTradeNo(out_trade_no);
        paymentRecord.setTotalFee(courseCatalogue.getPrice());
        paymentRecord.setTradeType("APP");
        paymentRecord.setCreateDate(new Date());
        paymentRecord.setRecType(1);
        paymentRecord.setPayType(1);
        paymentRecord.setAttr1(classId.toString());
        paymentRecord.setAttr2(code);
        paymentRecordBiz.insert(paymentRecord);


        WxMD5Util md5Util = new WxMD5Util();
        Map<String, String> returnMap = new HashMap<>();
        WXConfigUtil config = new WXConfigUtil();
        WXPay wxpay = new WXPay( config);
        Map<String, String> data = new HashMap<>();

        data.put("appid", config.getAppID());
        data.put("mch_id", config.getMchID());
        data.put("nonce_str", WXPayUtil.generateNonceStr());

        String body = "购买" + courseCatalogue.getCourseName();
        data.put("body", body);
        data.put("out_trade_no", out_trade_no);

        data.put("total_fee", total_fee);
        //自己的服务器IP地址
        data.put("spbill_create_ip", SPBILL_CREATE_IP);
        //异步通知地址（请注意必须是外网）
        data.put("notify_url", NOTIFY_URL);
        //交易类型
        data.put("trade_type", TRADE_TYPE_APP);
        //附加数据，在查询API和支付通知中原样返回，该字段主要用于商户携带订单的自定义数据
        data.put("attach", attach);
        String sign1 = md5Util.getSign(data);
        data.put("sign", sign1);

        try {
            //使用官方API请求预付订单
            Map<String, String> response = wxpay.unifiedOrder(data);
            System.out.println(response);
            String returnCode = response.get("return_code");    //获取返回码
            //若返回码为SUCCESS，则会返回一个result_code,再对该result_code进行判断
            if (returnCode.equals("SUCCESS")) {//主要返回以下5个参数
                String resultCode = response.get("result_code");
                returnMap.put("appid", response.get("appid"));
                returnMap.put("mch_id", response.get("mch_id"));
                returnMap.put("nonce_str", response.get("nonce_str"));
                returnMap.put("sign", response.get("sign"));
                if ("SUCCESS".equals(resultCode)) {//resultCode 为SUCCESS，才会返回prepay_id和trade_type
                    //获取预支付交易回话标志
                    returnMap.put("trade_type", response.get("trade_type"));
                    returnMap.put("prepay_id", response.get("prepay_id"));
                    return returnMap;
                } else {
                    //此时返回没有预付订单的数据
                    return returnMap;
                }
            } else {
                return returnMap;
            }
        } catch (Exception e) {
            System.out.println(e);
            //系统等其他错误的时候
        }
        return returnMap;
    }



    /**
     *
     * @param notifyData 异步通知后的XML数据
     * @return
     */
    @Override
    public String payBack(String notifyData) {
        WXConfigUtil config = null;
        try {
            config = new WXConfigUtil();
        } catch (Exception e) {
            e.printStackTrace();
        }
        WXPay wxpay = new WXPay((WXPayConfig) config);
        String xmlBack = "";
        Map<String, String> notifyMap = null;
        try {
            notifyMap = WXPayUtil.xmlToMap(notifyData);         // 调用官方SDK转换成map类型数据
            if (wxpay.isPayResultNotifySignatureValid(notifyMap)) {//验证签名是否有效，有效则进一步处理

                String return_code = notifyMap.get("return_code");//状态
                String out_trade_no = notifyMap.get("out_trade_no");//商户订单号
                if (return_code.equals("SUCCESS")) {
                    if (out_trade_no != null) {
                        // 注意特殊情况：订单已经退款，但收到了支付结果成功的通知，不应把商户的订单状态从退款改成支付成功
                        // 注意特殊情况：微信服务端同样的通知可能会多次发送给商户系统，所以数据持久化之前需要检查是否已经处理过了，处理了直接返回成功标志
                        //业务数据持久化

                        System.err.println("支付成功");

                        PaymentRecord paymentRecord1 = new PaymentRecord();
                        paymentRecord1.setOutTradeNo(out_trade_no);
                        PaymentRecord paymentRecord = paymentRecordBiz.selectOne(paymentRecord1);
                        if (paymentRecord != null) {
                            String status = notifyMap.get("result_code");
                            if (status.equals("SUCCESS")) {
                                // 如果状态是已经支付成功
                                //成功 更新状态
                                String tradeNo = notifyMap.get("transaction_id");
                                paymentRecord.setTradeNo(tradeNo);
                                paymentRecord.setTradeDate(new Date());
                                paymentRecord.setTradeStatus(status);
                                paymentRecordBiz.updateById(paymentRecord);
                                //@TODO APP服务器状态,返回支付结果与transaction_id

                                //根绝 订单号 查询 记录
                                String 	classId = paymentRecord.getAttr1();
                                String 	code = paymentRecord.getAttr2();
                                //开始插入数据
                                DefaultTransactionDefinition def = new DefaultTransactionDefinition();
                                def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
                                TransactionStatus statuss = txManager.getTransaction(def);
                                try {
                                    //购买课程后返金币和积分
                                    //365课程
                                    if(classId.equals("6")  || classId.equals("5") ){
                                        //账号判断是否有代理
                                        Example example = new Example(FamilyUser.class);
                                        example.createCriteria().andEqualTo("id", paymentRecord.getChargeUserId());
                                        List<FamilyUser> user = familyUserBiz.selectByExample(example);

                                        //不是代理时购买365自动成为教育专员
                                        if(!user.get(0).getFuserId().equals(user.get(0).getBaseId())){
                                            IdentityApply identityApply = new IdentityApply();
                                            identityApply.setUserId(user.get(0).getId());
                                            identityApply.setMobile(user.get(0).getMobile());
                                            identityApply.setName(user.get(0).getName());
                                            identityApply.setEmail(user.get(0).getEmail());
                                            identityApply.setStatus(2);

                                            //如果未有课程码  则生成


                                            if(user.get(0).getCourseCode() == null || "".equals(user.get(0).getCourseCode())){
                                                //生成邀请码并判断是否重复
                                                for(int i = 0; ; i ++) {
                                                    String codes = "K" + genRandomNum();
                                                    Example example8 = new Example(FamilyUser.class);
                                                    example8.createCriteria().andEqualTo("courseCode", codes);
                                                    List<FamilyUser> fu = familyUserBiz.selectByExample(example8);
                                                    if (fu.size() == 0) {
                                                        user.get(0).setCourseCode(codes);
                                                        break;
                                                    }
                                                }
                                                familyUserBiz.updateSelectiveById(user.get(0));

                                            }
                                            System.out.println("**************************");
                                            identityApplyBiz.insert(identityApply);
                                        }


                                        //若无代理  则不进行分账
                                        if(user.get(0).getTeacherId() != null){
                                            //获得代理信息  分账
                                            Example example1 = new Example(User.class);
                                            example1.createCriteria().andEqualTo("id", user.get(0).getTeacherId());
                                            List<User> baseuser = userBiz.selectByExample(example1);
                                            //判断代理是否开启
                                            if("1".equals(baseuser.get(0).getAttr5())) {
                                                //前一百个全额返还
                                                Integer num = Integer.parseInt(baseuser.get(0).getAttr7());
                                                if (num < 100) {
                                                    //修改金币和推广人数
                                                    User buser = baseuser.get(0);
                                                    Double price = Double.parseDouble(buser.getAttr6()) + paymentRecord.getTotalFee();
                                                    Integer n = num + 1;
                                                    buser.setAttr6(price.toString());
                                                    buser.setAttr7(n.toString());
                                                    userBiz.updateById(buser);
                                                    //添加分账记录
                                                    FamilyWalletRecord familyWalletRecord = new FamilyWalletRecord();
                                                    familyWalletRecord.setUserId(paymentRecord.getChargeUserId());
                                                    familyWalletRecord.setMechaismId(buser.getId());
                                                    familyWalletRecord.setType(1);
                                                    familyWalletRecord.setActualPayment(paymentRecord.getTotalFee());
                                                    familyWalletRecord.setRecordSn("代理全额返金币");
                                                    familyWalletRecord.setModifyTime(new Date());
                                                    familyWalletRecord.setCourseId(paymentRecord.getLessonId());
                                                    familyWalletRecord.setClassId(Integer.parseInt(classId));
                                                    familyWalletRecordBiz.insert(familyWalletRecord);
                                                } else {
                                                    //大于100人 分45.3%
                                                    //修改金币和推广人数
                                                    User buser = baseuser.get(0);
                                                    Double price = Double.parseDouble(buser.getAttr6()) + paymentRecord.getTotalFee() * 0.453;
                                                    Integer n = num + 1;
                                                    buser.setAttr6(price.toString());
                                                    buser.setAttr7(n.toString());
                                                    userBiz.updateById(buser);
                                                    //添加分账记录
                                                    FamilyWalletRecord familyWalletRecord = new FamilyWalletRecord();
                                                    familyWalletRecord.setUserId(paymentRecord.getChargeUserId());
                                                    familyWalletRecord.setMechaismId(buser.getId());
                                                    familyWalletRecord.setType(1);
                                                    familyWalletRecord.setRecordSn("代理返45.3%金币");
                                                    familyWalletRecord.setModifyTime(new Date());
                                                    familyWalletRecord.setCourseId(paymentRecord.getLessonId());
                                                    familyWalletRecord.setClassId(Integer.parseInt(classId));
                                                    familyWalletRecord.setActualPayment(paymentRecord.getTotalFee() * 0.453);
                                                    familyWalletRecordBiz.insert(familyWalletRecord);
                                                }
                                            }else{

                                            }
                                        }else{

                                        }

                                    }
                                    //520课程
                                    else if(classId.equals("7")){
                                        if(code != null && code != "" && !"undefined".equals(code)) {
                                            //判断邀请码是否正确
                                            Example example = new Example(FamilyUser.class);
                                            example.createCriteria().andEqualTo("courseCode", code);
                                            List<FamilyUser> user = familyUserBiz.selectByExample(example);
                                            //有教育专员
                                            if (user.size() > 0) {
                                                //教育专员分19.3%
                                                FamilyUser fu = user.get(0);
                                                Double price = fu.getPrice() + paymentRecord.getTotalFee() * 0.193;
                                                fu.setPrice(price);
                                                //分金币
                                                familyUserBiz.updateById(fu);
                                                //添加记录
                                                FamilyWalletRecord familyWalletRecord = new FamilyWalletRecord();
                                                familyWalletRecord.setUserId(paymentRecord.getChargeUserId());
                                                familyWalletRecord.setMechaismId(fu.getId());
                                                familyWalletRecord.setType(5);
                                                familyWalletRecord.setRecordSn("教育专员返19.3%金币");
                                                familyWalletRecord.setModifyTime(new Date());
                                                familyWalletRecord.setCourseId(paymentRecord.getLessonId());
                                                familyWalletRecord.setClassId(Integer.parseInt(classId));
                                                familyWalletRecord.setActualPayment(paymentRecord.getTotalFee() * 0.193);
                                                familyWalletRecordBiz.insert(familyWalletRecord);

                                                //判断是否有代理
                                                Example example1 = new Example(FamilyUser.class);
                                                example1.createCriteria().andEqualTo("id", paymentRecord.getChargeUserId());
                                                List<FamilyUser> users = familyUserBiz.selectByExample(example1);
                                                //代理分42.4%
                                                if (users.get(0).getTeacherId() != null) {
                                                    //获得代理信息  分账
                                                    Example example2 = new Example(User.class);
                                                    example2.createCriteria().andEqualTo("id", users.get(0).getTeacherId());
                                                    List<User> baseuser = userBiz.selectByExample(example2);
                                                    //判断代理是否开启
                                                    if("1".equals(baseuser.get(0).getAttr5())) {
                                                        User buser = baseuser.get(0);
                                                        Double p = Double.parseDouble(buser.getAttr6()) + paymentRecord.getTotalFee() * 0.424;
                                                        buser.setAttr6(p.toString());
                                                        userBiz.updateById(buser);
                                                        //添加分账记录
                                                        FamilyWalletRecord familyWalletRecords = new FamilyWalletRecord();
                                                        familyWalletRecords.setUserId(paymentRecord.getChargeUserId());
                                                        familyWalletRecords.setMechaismId(buser.getId());
                                                        familyWalletRecords.setType(1);
                                                        familyWalletRecords.setActualPayment(paymentRecord.getTotalFee() * 0.424);
                                                        familyWalletRecords.setRecordSn("代理返42.4%金币");
                                                        familyWalletRecords.setModifyTime(new Date());
                                                        familyWalletRecords.setCourseId(paymentRecord.getLessonId());
                                                        familyWalletRecords.setClassId(Integer.parseInt(classId));
                                                        familyWalletRecordBiz.insert(familyWalletRecords);
                                                    }else{
                                                    }
                                                } else {
                                                }
                                            } else {
                                                //无教育专员
                                                //判断是否有代理
                                                Example example1 = new Example(FamilyUser.class);
                                                example1.createCriteria().andEqualTo("id", paymentRecord.getChargeUserId());
                                                List<FamilyUser> users = familyUserBiz.selectByExample(example1);
                                                //代理分42.4%
                                                if (users.get(0).getTeacherId() != null) {
                                                    //获得代理信息  分账
                                                    Example example2 = new Example(User.class);
                                                    example2.createCriteria().andEqualTo("id", users.get(0).getTeacherId());
                                                    List<User> baseuser = userBiz.selectByExample(example2);
                                                    //判断代理是否开启
                                                    if("1".equals(baseuser.get(0).getAttr5())) {
                                                        User buser = baseuser.get(0);

                                                        Double p = Double.parseDouble(buser.getAttr6()) + paymentRecord.getTotalFee() * 0.424;
                                                        buser.setAttr6(p.toString());
                                                        userBiz.updateById(buser);
                                                        //添加分账记录
                                                        FamilyWalletRecord familyWalletRecords = new FamilyWalletRecord();
                                                        familyWalletRecords.setUserId(paymentRecord.getChargeUserId());
                                                        familyWalletRecords.setMechaismId(buser.getId());
                                                        familyWalletRecords.setType(1);
                                                        familyWalletRecords.setActualPayment(paymentRecord.getTotalFee() * 0.424);
                                                        familyWalletRecords.setRecordSn("代理返42.4%金币");
                                                        familyWalletRecords.setModifyTime(new Date());
                                                        familyWalletRecords.setCourseId(paymentRecord.getLessonId());
                                                        familyWalletRecords.setClassId(Integer.parseInt(classId));
                                                        familyWalletRecordBiz.insert(familyWalletRecords);
                                                    }else{

                                                    }
                                                } else {

                                                }
                                            }
                                        }
                                    }
                                }catch (Exception ex) {
                                    txManager.rollback(statuss);
                                    logger.error("网络连接超时", ex);
                                    //退款
                                }
                                txManager.commit(statuss);
                                logger.info("微信手机支付回调成功订单号:{}", out_trade_no);
                                xmlBack = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>" + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
                            } else {
                                logger.info("订单状态未知！");
                            }
                        } else {
                            logger.info("此单不存在！");
                        }
                    } else {
                        logger.info("微信手机支付回调失败订单号:{}", out_trade_no);
                        xmlBack = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
                    }
                }
                return xmlBack;
            } else {
                // 签名错误，如果数据里没有sign字段，也认为是签名错误
                //失败的数据要不要存储？
                logger.error("手机支付回调通知签名错误");
                xmlBack = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
                return xmlBack;
            }
        } catch (Exception e) {
            logger.error("手机支付回调通知失败", e);
            xmlBack = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
        }
        return xmlBack;
    }


    /**
     * 生成邀请码
     * @return
     */
    public String genRandomNum(){
        int  maxNum = 36;
        int i;
        int count = 0;
        char[] str = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K',
            'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
            'X', 'Y', 'Z',  '2', '3', '4', '5', '6', '7', '8', '9' };
        StringBuffer pwd = new StringBuffer("");
        Random r = new Random();
        while(count < 5){
            i = Math.abs(r.nextInt(maxNum));
            if (i >= 0 && i < str.length) {
                pwd.append(str[i]);
                count ++;
            }
        }
        return pwd.toString();
    }
}
